home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / weapon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  13.7 KB  |  526 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)weapon.c    3.1    93/07/10    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  *    This module contains code for calculation of "to hit" and damage
  7.  *    bonuses for any given weapon used, as well as weapons selection
  8.  *    code for monsters.
  9.  */
  10. #include "hack.h"
  11.  
  12. #ifdef OVLB
  13.  
  14. static NEARDATA const char kebabable[] = { S_XORN, S_DRAGON, S_NAGA, S_GIANT, 0 };
  15.  
  16. /*
  17.  *    hitval returns an integer representing the "to hit" bonuses
  18.  *    of "otmp" against the monster type "ptr".
  19.  */
  20. int
  21. hitval(otmp, ptr)
  22. struct    obj *otmp;
  23. struct    permonst *ptr;
  24. {
  25.     int    tmp = 0;
  26.  
  27.     if (otmp->oclass == WEAPON_CLASS ||
  28.         otmp->otyp == PICK_AXE || otmp->otyp == UNICORN_HORN)
  29.         tmp += otmp->spe;
  30.  
  31. /*    Put weapon specific "to hit" bonuses in below:        */
  32.     tmp += objects[otmp->otyp].oc_hitbon;
  33.  
  34. /*    Put weapon vs. monster type "to hit" bonuses in below:    */
  35.  
  36.     /* Blessed weapons used against undead or demons */
  37.     if(otmp->oclass == WEAPON_CLASS && otmp->blessed &&
  38.        (is_demon(ptr) || is_undead(ptr))) tmp += 2;
  39.  
  40.     if(otmp->otyp >= SPEAR && otmp->otyp <= JAVELIN &&
  41.        index(kebabable, ptr->mlet)) tmp += 2;
  42.  
  43.     /* Check specially named weapon "to hit" bonuses */
  44.     if (otmp->oartifact) tmp += spec_abon(otmp, ptr);
  45.     return tmp;
  46. }
  47.  
  48. /*
  49.  *    dmgval returns an integer representing the damage bonuses
  50.  *    of "otmp" against the monster type "ptr".
  51.  */
  52. int
  53. dmgval(otmp, ptr)
  54. struct    obj *otmp;
  55. struct    permonst *ptr;
  56. {
  57.     int    tmp = 0;
  58.  
  59.     if(otmp->otyp == CREAM_PIE)    return(0);
  60.  
  61.     if(ptr->msize >= MZ_HUMAN) {
  62.         if(objects[otmp->otyp].oc_wldam)
  63.         tmp = rnd(objects[otmp->otyp].oc_wldam);
  64.         switch (otmp->otyp) {
  65.         case CROSSBOW_BOLT:
  66.         case MORNING_STAR:
  67.         case PARTISAN:
  68.         case ELVEN_BROADSWORD:
  69.         case BROADSWORD:    tmp++; break;
  70.  
  71.         case FLAIL:
  72.         case RANSEUR:
  73.         case VOULGE:        tmp += rnd(4); break;
  74.  
  75.         case ACID_VENOM:
  76.         case HALBERD:
  77.         case SPETUM:        tmp += rnd(6); break;
  78.  
  79.         case BATTLE_AXE:
  80.         case BARDICHE:
  81.         case TRIDENT:        tmp += d(2,4); break;
  82.  
  83.         case TSURUGI:
  84.         case DWARVISH_MATTOCK:
  85.         case TWO_HANDED_SWORD:    tmp += d(2,6); break;
  86.         }
  87.     } else {
  88.         if(objects[otmp->otyp].oc_wsdam)
  89.         tmp = rnd(objects[otmp->otyp].oc_wsdam);
  90.         switch (otmp->otyp) {
  91.         case CROSSBOW_BOLT:
  92.         case MACE:
  93.         case WAR_HAMMER:
  94.         case FLAIL:
  95.         case SPETUM:
  96.         case TRIDENT:        tmp++; break;
  97.  
  98.         case BATTLE_AXE:
  99.         case BARDICHE:
  100.         case BILL_GUISARME:
  101.         case GUISARME:
  102.         case LUCERN_HAMMER:
  103.         case MORNING_STAR:
  104.         case RANSEUR:
  105.         case BROADSWORD:
  106.         case ELVEN_BROADSWORD:
  107.         case VOULGE:        tmp += rnd(4); break;
  108.  
  109.         case ACID_VENOM:    tmp += rnd(6); break;
  110.         }
  111.     }
  112.     if (otmp->oclass == WEAPON_CLASS || otmp->otyp == PICK_AXE
  113.                         || otmp->otyp == UNICORN_HORN)
  114.         tmp += otmp->spe;
  115.  
  116.     tmp -= otmp->oeroded;
  117.  
  118.     if (objects[otmp->otyp].oc_material <= LEATHER && thick_skinned(ptr))
  119.         /* thick skinned/scaled creatures don't feel it */
  120.         tmp = 0;
  121.     if (ptr == &mons[PM_SHADE] && objects[otmp->otyp].oc_material != SILVER)
  122.         tmp = 0;
  123.  
  124. /*    Put weapon vs. monster type damage bonuses in below:    */
  125.     if(otmp->oclass == WEAPON_CLASS) {
  126.         if (otmp->blessed && (is_undead(ptr) || is_demon(ptr)))
  127.         tmp += rnd(4);
  128.         if ((otmp->otyp == AXE || otmp->otyp == BATTLE_AXE)
  129.         && is_wooden(ptr))
  130.         tmp += rnd(4);
  131.         if (objects[otmp->otyp].oc_material == SILVER && hates_silver(ptr))
  132.         tmp += rnd(20);
  133.     }
  134.  
  135.     return(tmp);
  136. }
  137.  
  138. void
  139. set_uasmon()        /* update the "uasmon" structure */
  140. {
  141. #ifdef POLYSELF
  142.     if(u.umonnum >= 0) uasmon = &mons[u.umonnum];
  143.     else {
  144. #endif
  145.  
  146.         uasmon = &playermon;
  147.         playermon.mlevel = u.ulevel;
  148.         playermon.ac = u.uac;
  149.         playermon.mr = (u.ulevel > 8) ? 5 * (u.ulevel-7) : u.ulevel;
  150. #ifdef POLYSELF
  151.     }
  152. #endif
  153.     return;
  154. }
  155.  
  156. #endif /* OVLB */
  157. #ifdef OVL0
  158.  
  159. #define    Oselect(x)    if((otmp = oselect(mtmp, x))) return(otmp);
  160.  
  161. static struct obj * FDECL(oselect, (struct monst *,int));
  162.  
  163. static struct obj *
  164. oselect(mtmp, x)
  165. struct monst *mtmp;
  166. int x;
  167. {
  168.     struct obj *otmp;
  169.  
  170.     for(otmp=mtmp->minvent; otmp; otmp = otmp->nobj) {
  171.         if (otmp->otyp == x && touch_artifact(otmp,mtmp)
  172. #ifdef MUSE
  173.              && !(x == CORPSE && otmp->corpsenm != PM_COCKATRICE)
  174. #endif
  175.                                     )
  176.             return otmp;
  177.     }
  178.     return (struct obj *)0;
  179. }
  180.  
  181. static NEARDATA const int rwep[] =
  182.     { DWARVISH_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
  183.       SHURIKEN, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
  184.       CROSSBOW_BOLT, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE, ROCK,
  185.       LOADSTONE, LUCKSTONE, DART, /* BOOMERANG, */ CREAM_PIE
  186.       /* note: CREAM_PIE should NOT be #ifdef KOPS */
  187.       };
  188.  
  189. static struct obj *propellor;
  190.  
  191. struct obj *
  192. select_rwep(mtmp)    /* select a ranged weapon for the monster */
  193. register struct monst *mtmp;
  194. {
  195.     register struct obj *otmp;
  196.     int i;
  197.  
  198. #ifdef KOPS
  199.     char mlet = mtmp->data->mlet;
  200. #endif
  201.  
  202.     propellor = &zeroobj;
  203. #ifdef KOPS
  204.     if(mlet == S_KOP)    /* pies are first choice for Kops */
  205.         Oselect(CREAM_PIE);
  206. #endif
  207.     if(throws_rocks(mtmp->data))    /* ...boulders for giants */
  208.         Oselect(BOULDER);
  209.     /*
  210.      * other than these two specific cases, always select the
  211.      * most potent ranged weapon to hand.
  212.      */
  213.     for (i = 0; i < SIZE(rwep); i++) {
  214.         int prop;
  215.  
  216.         propellor = &zeroobj;
  217.         /* shooting gems from slings; this goes just before the darts */
  218.         if (rwep[i]==DART && !likes_gems(mtmp->data)
  219.             && (propellor = m_carrying(mtmp, SLING))) {
  220.         for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
  221.             if(otmp->oclass==GEM_CLASS &&
  222.                 (otmp->otyp != LOADSTONE || !otmp->cursed))
  223.             return(otmp);
  224.         }
  225.         }
  226.         prop = (objects[rwep[i]]).w_propellor;
  227.         if (prop > 0) {
  228.         switch (prop) {
  229.         case WP_BOW:
  230.           propellor = (oselect(mtmp, ELVEN_BOW));
  231.           if (!propellor) propellor = (oselect(mtmp, BOW));
  232.           if (!propellor) propellor = (oselect(mtmp, ORCISH_BOW));
  233.           break;
  234.         case WP_SLING:
  235.           propellor = (oselect(mtmp, SLING));
  236.           break;
  237.         case WP_CROSSBOW:
  238.           propellor = (oselect(mtmp, CROSSBOW));
  239.         }
  240. #ifdef MUSE
  241.         if ((otmp = MON_WEP(mtmp)) && otmp->cursed && otmp != propellor
  242.                 && mtmp->weapon_check == NO_WEAPON_WANTED)
  243.             propellor = 0;
  244. #endif
  245.         }
  246.         /* propellor = obj, propellor to use
  247.          * propellor = &zeroobj, doesn't need a propellor
  248.          * propellor = 0, needed one and didn't have one
  249.          */
  250.         if (propellor != 0) {
  251.         /* Note: cannot use m_carrying for loadstones, since it will
  252.          * always select the first object of a type, and maybe the
  253.          * monster is carrying two but only the first is unthrowable.
  254.          */
  255.         if (rwep[i] != LOADSTONE) {
  256. #ifdef MUSE
  257.             /* Don't throw a cursed weapon-in-hand */
  258.             if ((otmp = oselect(mtmp, rwep[i]))
  259.                 && (!otmp->cursed || otmp != MON_WEP(mtmp)))
  260.                 return(otmp);
  261. #else
  262.             Oselect(rwep[i]);
  263. #endif
  264.         } else for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
  265.             if (otmp->otyp == LOADSTONE && !otmp->cursed)
  266.             return otmp;
  267.         }
  268.         }
  269.       }
  270.  
  271.     /* failure */
  272.     return (struct obj *)0;
  273. }
  274.  
  275. /* 0 = used by any monster; 1 = only used by strong monsters */
  276. static NEARDATA const struct hwep { short otyp, big; } hwep[] = {
  277. #ifdef MUSE
  278.       {CORPSE,0},  /* cockatrice corpse */
  279. #endif
  280.       {TSURUGI,1}, {RUNESWORD,0},
  281.       {DWARVISH_MATTOCK,1}, {TWO_HANDED_SWORD,1}, {BATTLE_AXE,1},
  282.       {KATANA,0}, {UNICORN_HORN,1}, {CRYSKNIFE,0},
  283.       {TRIDENT,0}, {LONG_SWORD,0}, {ELVEN_BROADSWORD,0}, {BROADSWORD,0},
  284.       {LUCERN_HAMMER,1}, {SCIMITAR,1}, {SILVER_SABER,0}, {HALBERD,1},
  285.       {PARTISAN,1}, {LANCE,1}, {FAUCHARD,1}, {BILL_GUISARME,1},
  286.       {BEC_DE_CORBIN,1}, {GUISARME,1}, {RANSEUR,1}, {SPETUM,1},
  287.       {VOULGE,1}, {BARDICHE,0}, {MORNING_STAR,0}, {GLAIVE,0},
  288.       {ELVEN_SHORT_SWORD,0}, {DWARVISH_SHORT_SWORD,0}, {SHORT_SWORD,0},
  289.       {ORCISH_SHORT_SWORD,0}, {MACE,0}, {AXE,0}, {DWARVISH_SPEAR,0},
  290.       {ELVEN_SPEAR,0}, {SPEAR,0}, {ORCISH_SPEAR,0}, {FLAIL,0},
  291.       {QUARTERSTAFF,1}, {JAVELIN,0}, {AKLYS,0}, {CLUB,0}, {PICK_AXE,0},
  292. #ifdef KOPS
  293.       {RUBBER_HOSE,0},
  294. #endif /* KOPS */
  295.       {WAR_HAMMER,0}, {ELVEN_DAGGER,0}, {DAGGER,0}, {ORCISH_DAGGER,0},
  296.       {ATHAME,0}, {SCALPEL,0}, {KNIFE,0}, {WORM_TOOTH,0}, {BULLWHIP,0}
  297.     };
  298.  
  299. struct obj *
  300. select_hwep(mtmp)    /* select a hand to hand weapon for the monster */
  301. register struct monst *mtmp;
  302. {
  303.     register struct obj *otmp;
  304.     register int i;
  305.     register const struct hwep *hw;
  306.     boolean strong = strongmonst(mtmp->data);
  307.  
  308.     if(is_giant(mtmp->data))    /* giants just love to use clubs */
  309.         Oselect(CLUB);
  310.  
  311.     /* only strong monsters can wield big (esp. long) weapons */
  312.     /* all monsters can wield the remaining weapons */
  313.     for (i = 0, hw = hwep; i < SIZE(hwep); i++, hw++)
  314.         if ((strong || !hw->big) &&
  315. #ifdef MUSE
  316.           (!objects[hw->otyp].oc_bimanual ||
  317.                     (mtmp->misc_worn_check & W_ARMS)) &&
  318. #endif
  319.     (objects[hw->otyp].oc_material != SILVER || !hates_silver(mtmp->data)))
  320.         Oselect(hw->otyp);
  321.  
  322.     /* failure */
  323.     return (struct obj *)0;
  324. }
  325.  
  326. #ifdef MUSE
  327. /* Called after polymorphing a monster, robbing it, etc....  Monsters
  328.  * otherwise never unwield stuff on their own.  Shouldn't print messages.
  329.  */
  330. void
  331. possibly_unwield(mon)
  332. register struct monst *mon;
  333. {
  334.     register struct obj *obj;
  335.     struct obj *otmp, *backobj, *mw_tmp;
  336.  
  337.     if (!(mw_tmp = MON_WEP(mon)))
  338.         return;
  339.     for(obj=mon->minvent; obj; obj=obj->nobj)
  340.         if (obj == mw_tmp) break;
  341.     if (!obj) { /* The weapon was stolen or destroyed */
  342.         MON_NOWEP(mon);
  343.         mon->weapon_check = NEED_WEAPON;
  344.         return;
  345.     }
  346.     if (!attacktype(mon->data, AT_WEAP)) {
  347.         mw_tmp->owornmask &= ~W_WEP;
  348.         MON_NOWEP(mon);
  349.         mon->weapon_check = NO_WEAPON_WANTED;
  350.         if (cansee(mon->mx, mon->my)) {
  351.             pline("%s drops %s.", Monnam(mon),
  352.                 distant_name(obj, doname));
  353.         }
  354.         backobj = 0;
  355.         for(otmp = mon->minvent; otmp; otmp = otmp->nobj) {
  356.             /* flooreffects unnecessary, can't wield boulders */
  357.             if (otmp == obj) {
  358.                 if (!backobj) mon->minvent = otmp->nobj;
  359.                 else backobj->nobj = otmp->nobj;
  360.                 place_object(otmp, mon->mx, mon->my);
  361.                 otmp->nobj = fobj;
  362.                 fobj = otmp;
  363.                 stackobj(fobj);
  364.                 if(cansee(mon->mx,mon->my))
  365.                     newsym(mon->mx, mon->my);
  366.                 break;
  367.             }
  368.             backobj = otmp;
  369.         }
  370.         return;
  371.     }
  372.     /* The remaining case where there is a change is where a monster
  373.      * is polymorphed into a stronger/weaker monster with a different
  374.      * choice of weapons.  This has no parallel for players.  It can
  375.      * be handled by waiting until mon_wield_item is actually called.
  376.      * Though the monster still wields the wrong weapon until then,
  377.      * this is OK since the player can't see it.
  378.      * Note that if there is no change, setting the check to NEED_WEAPON
  379.      * is harmless.
  380.      * Possible problem: big monster with big cursed weapon gets
  381.      * polymorphed into little monster.  But it's not quite clear how to
  382.      * handle this anyway....
  383.      */
  384.     mon->weapon_check = NEED_WEAPON;
  385.     return;
  386. }
  387.  
  388. /* Let a monster try to wield a weapon, based on mon->weapon_check.
  389.  * Returns 1 if the monster took time to do it, 0 if it did not.
  390.  */
  391. int
  392. mon_wield_item(mon)
  393. register struct monst *mon;
  394. {
  395.     struct obj *obj;
  396.  
  397.     /* This case actually should never happen */
  398.     if (mon->weapon_check == NO_WEAPON_WANTED) return 0;
  399.  
  400.     switch(mon->weapon_check) {
  401.         case NEED_HTH_WEAPON:
  402.             obj = select_hwep(mon);
  403.             break;
  404.         case NEED_RANGED_WEAPON:
  405.             (void)select_rwep(mon);
  406.             obj = propellor;
  407.             break;
  408.         case NEED_PICK_AXE:
  409.             obj = m_carrying(mon, PICK_AXE);
  410.             break;
  411.         default: impossible("weapon_check %d for %s?",
  412.                 mon->weapon_check, mon_nam(mon));
  413.             return 0;
  414.     }
  415.     if (obj && obj != &zeroobj) {
  416.         struct obj *mw_tmp = MON_WEP(mon);
  417.         if (mw_tmp == obj) { /* already wielding it */
  418.             mon->weapon_check = NEED_WEAPON;
  419.             return 0;
  420.         }
  421.         /* Actually, this isn't necessary--as soon as the monster
  422.          * wields the weapon, the weapon welds itself, so the monster
  423.          * can know it's cursed and needn't even bother trying.
  424.          * Still....
  425.          */
  426.         if (mw_tmp && mw_tmp->cursed && mw_tmp->otyp != CORPSE) {
  427.             if (canseemon(mon)) {
  428.             char welded_buf[BUFSZ];
  429.  
  430.             Sprintf(welded_buf, "%s welded to %s hand%s",
  431.                 (mw_tmp->quan == 1L) ? "is" : "are",
  432.                 his[pronoun_gender(mon)],
  433.                 objects[mw_tmp->otyp].oc_bimanual ? "s" : "");
  434.  
  435.             if (obj->otyp == PICK_AXE) {
  436.                 pline("Since %s weapon%s %s,",
  437.                   s_suffix(mon_nam(mon)),
  438.                   plur(mw_tmp->quan), welded_buf);
  439.                 pline("%s cannot wield that %s.",
  440.                 mon_nam(mon), xname(obj));
  441.             } else {
  442.                 pline("%s tries to wield %s.", Monnam(mon),
  443.                 doname(obj));
  444.                 pline("%s %s %s!",
  445.                   s_suffix(Monnam(mon)),
  446.                   xname(mw_tmp), welded_buf);
  447.             }
  448.             mw_tmp->bknown = 1;
  449.             }
  450.             mon->weapon_check = NO_WEAPON_WANTED;
  451.             return 1;
  452.         }
  453.         mon->mw = obj;        /* wield obj */
  454.         if (mw_tmp) mw_tmp->owornmask &= ~W_WEP;
  455.         mon->weapon_check = NEED_WEAPON;
  456.         if (canseemon(mon)) {
  457.             pline("%s wields %s!", Monnam(mon), doname(obj));
  458.             if (obj->cursed && obj->otyp != CORPSE) {
  459.                 pline("%s %s to %s hand!",
  460.                     The(xname(obj)),
  461.                     (obj->quan == 1L) ? "welds itself"
  462.                         : "weld themselves",
  463.                     s_suffix(mon_nam(mon)));
  464.                 obj->bknown = 1;
  465.             }
  466.         }
  467.         obj->owornmask = W_WEP;
  468.         return 1;
  469.     }
  470.     mon->weapon_check = NEED_WEAPON;
  471.     return 0;
  472. }
  473. #endif
  474.  
  475. int
  476. abon() {    /* attack bonus for strength & dexterity */
  477.     int    sbon;
  478.     register int    str = ACURR(A_STR), dex = ACURR(A_DEX);
  479.  
  480. #ifdef POLYSELF
  481.     if (u.umonnum >= 0) return(adj_lev(&mons[u.umonnum])-3);
  482. #endif
  483.     if (str < 6) sbon = -2;
  484.     else if (str < 8) sbon = -1;
  485.     else if (str < 17) sbon = 0;
  486.     else if (str < 69) sbon = 1;    /* up to 18/50 */
  487.     else if (str < 118) sbon = 2;
  488.     else sbon = 3;
  489. /*
  490.  *    Temporary kludge - make it a bit easier for a low level character
  491.  *               to hit until we tune the game a little better.
  492.  */
  493.     sbon += (u.ulevel < 3) ? 1 : 0;
  494.  
  495.     if (dex < 4) return(sbon-3);
  496.     else if (dex < 6) return(sbon-2);
  497.     else if (dex < 8) return(sbon-1);
  498.     else if (dex < 14) return(sbon);
  499.     else return(sbon + dex-14);
  500. }
  501.  
  502. #endif /* OVL0 */
  503. #ifdef OVL1
  504.  
  505. int
  506. dbon() {    /* damage bonus for strength */
  507.     register int    str = ACURR(A_STR);
  508.  
  509. #ifdef POLYSELF
  510.     if (u.umonnum >= 0) return(0);
  511. #endif
  512.  
  513.     if (str < 6) return(-1);
  514.     else if (str < 16) return(0);
  515.     else if (str < 18) return(1);
  516.     else if (str == 18) return(2);        /* up to 18 */
  517.     else if (str < 94) return(3);        /* up to 18/75 */
  518.     else if (str < 109) return(4);        /* up to 18/90 */
  519.     else if (str < 118) return(5);        /* up to 18/99 */
  520.     else return(6);
  521. }
  522.  
  523. #endif /* OVL1 */
  524.  
  525. /*weapon.c*/
  526.